using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Microsoft.SPOT;
using Socket = System.Net.Sockets.Socket;

namespace CobraController
{
  public class SocketServer
  {
    public SocketServer()
    {
			
      // Create a socket, bind it to the server's port, and listen for client 
      // connections.
      Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Settings.CobraSocketPort);
      server.Bind(localEndPoint);
      server.Listen(Int32.MaxValue);

      while (true)
      {
        // Wait for a client to connect.
        Socket clientSocket = server.Accept();

        // Process the client request.  true means asynchronous.
        new ProcessClientRequest(clientSocket, true);
      }
    }

        /// <summary>
    /// Processes a client request.
    /// </summary>
    internal sealed class ProcessClientRequest
    {
      private Socket m_clientSocket;

      /// <summary>
      /// The constructor calls another method to handle the request, but can 
      /// optionally do so in a new thread.
      /// </summary>
      /// <param name="clientSocket"></param>
      /// <param name="asynchronously"></param>
      public ProcessClientRequest(Socket clientSocket, Boolean asynchronously)
      {
        m_clientSocket = clientSocket;

        if (asynchronously)
          // Spawn a new thread to handle the request.
          new Thread(ProcessRequest).Start();
        else ProcessRequest();
      }

      /// <summary>
      /// Processes the request.
      /// </summary>
      private void ProcessRequest()
      {
        const Int32 c_microsecondsPerSecond = 1000000;

        m_clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, -2);

        // 'using' ensures that the client's socket gets closed.
        using (m_clientSocket)
        {
          // Wait for the client request to start to arrive.
          Byte[] buffer = new Byte[1024];
          if (m_clientSocket.Poll(5 * c_microsecondsPerSecond, SelectMode.SelectRead))
          {
            // If 0 bytes in buffer, then the connection has been closed, 
            // reset, or terminated.
            if (m_clientSocket.Available == 0)
              return;

            // Read the first chunk of the request (we don't actually do 
            // anything with it).
            
            Int32 bytesRead = m_clientSocket.Receive(buffer, m_clientSocket.Available, SocketFlags.None);
            //string recmesg = Helpers.Decode(buffer);
            //Debug.Print("---At " + DateTime.Now.ToString() + " I received: " + recmesg + " ---");
            // Return a static HTML document to the client.
            // String s = "<ACK>";
            //MessageHandler.ParseMessage(Helpers.Decode(buffer));
            MessageEventHandler.onMessageEvent(Helpers.Decode(buffer));
            //m_clientSocket.Send(Encoding.UTF8.GetBytes(s));
          }
        }
      }
    }
  }
}
